package com.kuang.blockqueue;

import com.sun.media.sound.SoftTuning;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.TimeUnit;

/**
 * 阻塞队列：  BlockingQueue
 *      下面有：
 *          ArrayBlockingQueue   (这个)
 *          LinkedBlockingDeque
 *      什么情况下对列发生阻塞?
 *          FIFO先进先出
 *          写入：如果队列满了，就必须阻塞等待
 *          取：如果是队列为空，必须阻塞等待生产
 *      什么情况下使用阻塞队列？
 *          多线程并发处理，线程池！
 *      阻塞队列有哪些操作？
 *          添加、移除两个操作
 *      四组API,实现不同效果：
 *          1.抛出异常
 *              检查队首元素：element()
 *              add() remove() 组合处理添加、移除操作
 *              插入成功返回true,队列满了，插入失败返回异常
 *              非法状态异常：IllegalStateException Exception：Queue full
 *          2.不会抛出异常
 *              检查队首元素：peek()
 *              offer() poll() 组合处理添加、移除操作
 *              插入成功返回true,队列满了，插入失败返回false
 *              如果队列满了，再添加时，不会抛出异常
 *          3.阻塞等待
 *              put() task() 组合处理添加、移除操作
 *              无返回值
 *              如果队列满了，再添加时，会一直阻塞等待，不结束
 *          4.超时等待
 *              offer(,,) poll(,) 组合处理添加、移除操作
 *              如果队列满了，再添加时，会一直阻塞等待，直到超多一定时间，就不等待了
 */
public class BlockingQueueTest {
    public static void main(String[] args) throws InterruptedException {
        //test1();
        //test2();
        //test3();
        test4();
    }

    /*
        1、抛出异常
     */
    public static void test1(){
        // 队列大小3
        ArrayBlockingQueue<Object> blockingQueue = new ArrayBlockingQueue<>(3);
        // add 存,返回true|false
        System.out.println(blockingQueue.add("a"));
        System.out.println(blockingQueue.add("b"));
        System.out.println(blockingQueue.add("c"));
        // 查看队首元素
        System.out.println(blockingQueue.element());
        System.out.println("========多余的开始进入=======");
        System.out.println(blockingQueue.add("d"));
        // remove 取,返回true|false
        System.out.println(blockingQueue.remove("a"));
        System.out.println(blockingQueue.remove("b"));
        System.out.println(blockingQueue.remove("c"));
        /*
            true
            true
            true
            a
            ========多余的开始进入=======
            Exception：IllegalStateException非法状态异常 Queue full
         */
    }

    /*
       2、不会抛出异常
     */
    public static void test2(){
        // 队列大小3
        ArrayBlockingQueue<Object> blockingQueue = new ArrayBlockingQueue<>(3);
        // offer 存,返回true|false
        System.out.println(blockingQueue.offer("a"));
        System.out.println(blockingQueue.offer("b"));
        System.out.println(blockingQueue.offer("c"));
        // 查看队首元素
        System.out.println(blockingQueue.peek());
        System.out.println("========多余的开始进入=======");
        System.out.println(blockingQueue.offer("d"));
        // poll 取,返回true|false
        System.out.println(blockingQueue.poll());
        System.out.println(blockingQueue.poll());
        System.out.println(blockingQueue.poll());
        /*
            true
            true
            true
            a
            ========多余的开始进入=======
            false
            a
            b
            c
         */
    }


    /*
        3、阻塞等待
    */
    public static void test3() throws InterruptedException {
        // 队列大小3
        ArrayBlockingQueue<Object> blockingQueue = new ArrayBlockingQueue<>(3);
        // offer 存,无返回值
        blockingQueue.put("a");
        blockingQueue.put("b");
        blockingQueue.put("c");
        System.out.println("========多余的开始进入=======");
        blockingQueue.put("d");
        // poll 取,无返回值
        blockingQueue.take();
        blockingQueue.take();
        blockingQueue.take();
        /*
            ========多余的开始进入=======
            一直阻塞，不结束
         */
    }

    /*
        4、超时等待
    */
    public static void test4() throws InterruptedException {
        // 队列大小3
        ArrayBlockingQueue<Object> blockingQueue = new ArrayBlockingQueue<>(3);
        // offer 存,无返回值
        blockingQueue.offer("a");
        System.out.println("放入a");
        blockingQueue.offer("b");
        System.out.println("放入b");
        blockingQueue.offer("c");
        System.out.println("放入c");
        System.out.println("========多余的开始进入=======");
        blockingQueue.offer("d",5, TimeUnit.SECONDS);  // 等待超过5秒，还没有位置，就结束等待
        // poll 取,无返回值
        blockingQueue.poll();
        System.out.println("取出a");
        blockingQueue.poll();
        System.out.println("取出b");
        blockingQueue.poll();
        System.out.println("取出c");
        System.out.println("========开始取出队列已经没有的=======");
        blockingQueue.poll(5,TimeUnit.SECONDS); // 等待超过2秒，还没有东西可以拿，就结束等待，不拿了，下面没有执行语句了，就退出
        /*
            放入a
            放入b
            放入c
            ========多余的开始进入=======
            取出a
            取出b
            取出c
            ========开始取出队列已经没有的=======
            等待5s后，没有进入的可以取出，退出
         */
    }


}
